﻿/*
 * MemoryBlock.h
 */
#ifndef __GDK_MEMORYBLOCK_H__
#define __GDK_MEMORYBLOCK_H__

#include <gdk/core/Types.h>
#include <gdk/core/Exception.h>
#include <gdk/core/Memory.h>


namespace gdk
{



template<ssize_t TyMemSize>
class MemoryBlock
{
public:
	enum MemSize
	{
		MEMSIZE = TyMemSize,
	};

private:
	ssize_t	_position;
	char	_buffer[MEMSIZE];


public:
	MemoryBlock(void)
		: _position(0)
	{
	}
	ssize_t getPosition(void) const
	{
		return _position;
	}
	ssize_t setPosition(ssize_t pos)
	{
		return (_position = (pos <= 0 ? 0 : (pos >= MEMSIZE ? MEMSIZE : pos)));
	}
	ssize_t read(void *buf, ssize_t size)
	{
		GDK_ASSERT(size >= 0);
		if (size > 0) GDK_ASSERT(buf != NULL);

		ssize_t n = MEMSIZE - _position;
		if (size > n)
		{
			if (n <= 0)
			{
				return 0;
			}

			size = n;
		}
		else if (size < 0) size = 0;

		memCopy(buf, _buffer + _position, size);
		_position += size;

		return size;
	}
	ssize_t write(const void *data, ssize_t size)
	{
		GDK_ASSERT(size >= 0);
		if (size > 0) GDK_ASSERT(data != NULL);

		ssize_t n = MEMSIZE - _position;
		if (size > n)
		{
			if (n <= 0)
			{
				return -1;
			}

			size = n;
		}
		else if (size < 0) size = 0;

		memCopy(_buffer + _position, data, size);
		_position += size;

		return size;
	}
	__INLINE__ void* getBuffer(void) { return _buffer; }
	__INLINE__ const void* getBuffer(void) const { return _buffer; }

public:
	template<typename TyIs, ssize_t Ty> friend TyIs& operator >>(TyIs &is, MemoryBlock<Ty> &o) __THROW1;
	template<typename TyOs, ssize_t Ty> friend TyOs& operator <<(TyOs &os, MemoryBlock<Ty> const &o) __THROW1;
};


template<typename TyIs, ssize_t TyMemSize>
TyIs& operator >>(TyIs &is, MemoryBlock<TyMemSize> &o) __THROW1
{
	is >> o._position;
	if (sizeof(o._buffer) != is.read(o._buffer, sizeof(o._buffer)))
	{
		__THROW__(__TEXT__("TyIs& operator >>(TyIs &, MemoryBlock &)"));
	}
	return is;
}
template<typename TyOs, ssize_t TyMemSize>
TyOs& operator <<(TyOs &os, const MemoryBlock<TyMemSize> &o) __THROW1
{
	os << o._position;
	if (sizeof(o._buffer) != os.write(o._buffer, sizeof(o._buffer)))
	{
		__THROW__(__TEXT__("TyOs& operator <<(TyOs &, const MemoryBlock &)"));
	}
	return os;
}



}//namespace gdk









#endif //__GDK_MEMORYBLOCK_H__
